#!/usr/bin/env python

import sys
import os
from genshi.template._ast24 import ImportFrom
localDir = os.path.dirname(__file__)
absDir = os.path.join(os.getcwd(), localDir)

import cherrypy
from genshi.template import TemplateLoader
loader = TemplateLoader('../html', auto_reload=True)

import cgi
import tempfile
import random
import json
import couchdbkit

import importFromMBox 
import importVC
import importJIRA
from couchdb_util import viewCreator
from couchdb_util import viewGetter
from filter import filter_fun, filterClass, group_result


class myFieldStorage(cgi.FieldStorage):
    """Our version uses a named temporary file instead of the default
    non-named file; keeping it visibile (named), allows us to create a
    2nd link after the upload is done, thus avoiding the overhead of
    making a copy to the destination filename."""
    
    def make_file(self, binary=None):
        return tempfile.NamedTemporaryFile()

def noBodyProcess():
    """Sets cherrypy.request.process_request_body = False, giving
    us direct control of the file upload destination. By default
    cherrypy loads it to memory, we are directing it to disk."""
    cherrypy.request.process_request_body = False

cherrypy.tools.noBodyProcess = cherrypy.Tool('before_request_body', noBodyProcess)


class Root(object):
	#class used to display the index.html

    @cherrypy.expose
    def index(self):
        tmpl = loader.load('index.html')
        return tmpl.generate().render('html', doctype='html')


@cherrypy.expose
@cherrypy.tools.noBodyProcess()
def upload(couchdb=None, database=None, maillist=None, datafile=None):
	# method tosave an uploaded file containing email in MBox format to couchdb 
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour

	#return str(couchdb) +"<br>" + str(database) + "<br>" + str(maillist) + "<br>"+ str(datafile.filename)

	# convert the header keys to lower case
    lcHDRS = {}
    for key, val in cherrypy.request.headers.iteritems():
        lcHDRS[key.lower()] = val
        
    # at this point we could limit the upload on content-length...
    # incomingBytes = int(lcHDRS['content-length'])
        
    # create our version of cgi.FieldStorage to parse the MIME encoded
    # form data where the file is contained
    formFields = myFieldStorage(fp=cherrypy.request.rfile, headers=lcHDRS, environ={'REQUEST_METHOD':'POST'}, keep_blank_values=True)
        
    # we now create a 2nd link to the file, using the submitted
    # filename; if we renamed, there would be a failure because
    # the NamedTemporaryFile, used by our version of cgi.FieldStorage,
    # explicitly deletes the original filename
    datafile = formFields['datafile']
    maillist = str(formFields['maillist'].value)
    couchdb = str(formFields['couchdb'].value)
    database = str(formFields['database'].value)

	# save the file in tmp
    rand = random.randint(1, 200)	
    os.link(datafile.file.name, '/tmp/'+str(rand)+datafile.filename)
    
    thread = importFromMBox.MainThread(maillist, '/tmp/'+str(rand)+datafile.filename, couchdb, database)
    thread.start()
    tmpl = loader.load('importing.html')
    return tmpl.generate().render('html', doctype='html')


# remove any limit on the request body size; cherrypy's default is 100MB
# (maybe we should just increase it ?)
cherrypy.server.max_request_body_size = 0

# increase server socket timeout to 60s; we are more tolerant of bad
# quality client-server connections (cherrypy's defult is 10s)
cherrypy.server.socket_timeout = 60

@cherrypy.expose
def vcimporting(couchdb, database, software, repo, name):
    # method to import data form version control
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour
    if software=="git":
        thread = importVC.MainGitThread(repo, couchdb, database, name)
        thread.start()
        tmpl = loader.load('importing.html')
        return tmpl.generate().render('html', doctype='html')

    elif software=="subversion":
        #import svn
        thread = importVC.MainSVNThread(repo,couchdb, database, name)
        thread.start()
        tmpl = loader.load('importing.html')
        return tmpl.generate().render('html', doctype='html')
    else:
        return "Not yet implemented"

@cherrypy.expose
def bugimporting(couchdb, database, jira, name):
    # method to import data form bug tracker
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour
    thread = importJIRA.MainJIRAThread(jira, name, couchdb, database)
    thread.start()
    tmpl = loader.load('importing.html')
    return tmpl.generate().render('html', doctype='html')
    
@cherrypy.expose
def iexplore(couchdb=None, database=None, button=None):
    # select the database to explore
    if couchdb is None and database is None:
        tmpl = loader.load('iexplore.html')
        return tmpl.generate(cdb="", db=None, button="Use this address").render('html', doctype='html')
    elif not(couchdb is None) and database is None:
        tmpl = loader.load('iexplore.html')
        serv = couchdbkit.Server(couchdb)
        return tmpl.generate(cdb=couchdb, db=serv.all_dbs(), button="choose this database").render('html', doctype='html')
    elif not(couchdb is None) and not(database is None):
        viewCreator.addViews(couchdb, database)
        return visualization(couchdb, database)
    else:
        return "Problem occurred: <br>"+str(couchdb)+ "  " + str(database)
    
@cherrypy.expose
def visualization(couchdb, database):
    # return the visualization for the given database divided by month
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour
    commits = viewGetter.getMonthCommitView(couchdb, database)
    emails = viewGetter.getMonthEmailView(couchdb, database)
    issues = viewGetter.getMonthIssueView(couchdb, database)
    tmpl = loader.load('visualization.html')
    return tmpl.generate(couchdb=couchdb, project=database, commits=commits, emails=emails, issues=issues, time="month").render('html', doctype='html')

@cherrypy.expose
def visualizationYear(couchdb, database):
    # return the visualization for the given database divided by year
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour
    commits = viewGetter.getYearCommitView(couchdb, database)
    emails = viewGetter.getYearEmailView(couchdb, database)
    issues = viewGetter.getYearIssueView(couchdb, database)
    tmpl = loader.load('visualization.html')
    return tmpl.generate(couchdb=couchdb, project=database, commits=commits, emails=emails, issues=issues, time="year").render('html', doctype='html')

@cherrypy.expose
def visualizationDay(couchdb, database):
    # return the visualization for the given database divided by day
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour
    commits = viewGetter.getDayCommitView(couchdb, database)
    emails = viewGetter.getDayEmailView(couchdb, database)
    issues = viewGetter.getDayIssueView(couchdb, database)
    tmpl = loader.load('visualization.html')
    return tmpl.generate(couchdb=couchdb, project=database, commits=commits, emails=emails, issues=issues, time="day").render('html', doctype='html')

@cherrypy.expose
def getdata(couchdb, database, type, date, datelen):
    # return requested data to the client
    print str(type)+" "+str(date)+" "+str(datelen)
    if(datelen==7 or datelen=='7'):
        # date specifies a year/month like YYYY-MM
        if type=="emails":
            emails = viewGetter.getEmailForMonth(couchdb, database, date)
            return emails
        elif type=="commits":
            commits = viewGetter.getCommitForMonth(couchdb, database, date)
            return commits
        elif type=="issues":
            issue = viewGetter.getIssueForMonth(couchdb, database, date)
            return issue
    elif(datelen==4 or datelen=='4'):
        if type=="emails":
            emails = viewGetter.getEmailForYear(couchdb, database, date)
            return emails
        elif type=="commits":
            commits = viewGetter.getCommitForYear(couchdb, database, date)
            return commits
        elif type=="issues":
            issue = viewGetter.getIssueForYear(couchdb, database, date)
            return issue
    elif(datelen==10 or datelen=='10'):
        if type=="emails":
            emails = viewGetter.getEmailForDay(couchdb, database, date)
            return emails
        elif type=="commits":
            commits = viewGetter.getCommitForDay(couchdb, database, date)
            return commits
        elif type=="issues":
            issue = viewGetter.getIssueForDay(couchdb, database, date)
            return issue
    else:
        print "Error occurred"
    # if arrived here something went wrong    
    return "No data found"

@cherrypy.expose
def getsingle_email(couchdb, database, id):
    # function to return an email from the database given the email's id
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour
    id=id.replace("___","&")
    doc = viewGetter.getDocumentById(couchdb, database, id)
    tmpl = loader.load('showemail.html')
    return tmpl.generate(project=database, sender=doc['sender'], subject=doc['subject'], date=doc['date'], email=json.dumps(doc)).render('html', doctype='html')


@cherrypy.expose
def getsingle_commit(couchdb, database, id):
     # function to return a commit from the database given the commit's id
     id=id.replace("___","&")
     #print "-commit "+str(couchdb)+" "+str(database)+" "+id
     cherrypy.response.timeout = 3600 #set the timeout to 1 hour
     doc = viewGetter.getDocumentById(couchdb, database, id)
     tmpl = loader.load('showcommit.html')
     return tmpl.generate(project=database, log=doc["logMessage"], date=doc["date"], rev=doc["revision"], author=doc["author"], committer=doc["committer"], commit=json.dumps(doc)).render('html', doctype='html')

@cherrypy.expose
def getsingle_issue(couchdb, database, id):
     # function to return an issue from the database given the issue's id
     cherrypy.response.timeout = 3600 #set the timeout to 1 hour
     id=id.replace("___","&")
     doc = viewGetter.getDocumentById(couchdb, database, id)
     tmpl = loader.load('showissue.html')
     return tmpl.generate(project=database, sum=doc["summary"], dateRep=doc["dateReported"], dateUp=doc["dateUpdated"], reporter=doc["author"], assignee=doc["assignee"], status=doc["status"], priority=doc["priority"], resolution=doc["resolution"], issue=json.dumps(doc)).render('html', doctype='html')

@cherrypy.expose
def filterData(couchdb, database, filterList, dateType):
    # filters data with given filters and group result according to date
    # dateType is month, year or day
    cherrypy.response.timeout = 3600 #set the timeout to 1 hour
    filters = filter_fun.create_filters_fromlistDict(json.loads(filterList), database)
    print filters
    commits, emails, issues = filter_fun.divideFiltersByType(filters, database, couchdb)
    if commits:
        print "commits#:",len(commits)
        comm_group = group_result.groupList(commits, couchdb, database, dateType)
        print comm_group
    else:
        comm_group=[]
    if emails:
        print "emails#:",len(emails)
        email_group = group_result.groupList(emails, couchdb, database, dateType)
    else:
        email_group=[]
    if issues:
        print "issues#:",len(issues)
        issue_group = group_result.groupList(issues, couchdb, database, dateType)
    else:
        issue_group=[]
    # get non filtered data
    if dateType=="month":
        nf_commits = viewGetter.getMonthCommitView(couchdb, database)
        nf_emails = viewGetter.getMonthEmailView(couchdb, database)
        nf_issues = viewGetter.getMonthIssueView(couchdb, database)
    elif dateType=="year":
        nf_commits = viewGetter.getYearCommitView(couchdb, database)
        nf_emails = viewGetter.getYearEmailView(couchdb, database)
        nf_issues = viewGetter.getYearIssueView(couchdb, database)
    elif dateType=="day":
        nf_commits = viewGetter.getDayCommitView(couchdb, database)
        nf_emails = viewGetter.getDayEmailView(couchdb, database)
        nf_issues = viewGetter.getDayIssueView(couchdb, database)
    comm_group = json.dumps(comm_group)
    email_group = json.dumps(email_group)
    issue_group = json.dumps(issue_group)
    tmpl = loader.load('filtervisualization.html')
    return tmpl.generate(couchdb=couchdb, project=database, commits=nf_commits, emails=nf_emails, issues=nf_issues, time=dateType, filter_commits=comm_group, filter_emails=email_group, filter_issues=issue_group).render('html', doctype='html')


# load server configurations
conf = os.path.join(os.path.dirname(__file__), 'server.config')

# exposes the functions for handling page request
root = Root()
root.upload = upload
root.vcimporting = vcimporting
root.bugimporting = bugimporting
root.iexplore = iexplore
root.visualization = visualization
root.visualizationYear = visualizationYear
root.visualizationDay = visualizationDay
root.getdata = getdata
root.getsingle_email = getsingle_email
root.getsingle_commit = getsingle_commit
root.getsingle_issue = getsingle_issue
root.filterData = filterData

# start the server
cherrypy.tree.mount(root, '/', config=conf)
cherrypy.engine.start()
cherrypy.engine.block()



